package org.codehaus.activemq.filter;

import javax.jms.JMSException;
import javax.jms.Message;

public abstract class UnaryExpression implements Expression {
	protected Expression right;

	public static Expression createNegate(Expression left) {
		return new UnaryExpression(left) {
			public Object evaluate(Message message) throws JMSException {
				Object lvalue = this.right.evaluate(message);
				if (lvalue == null) {
					return null;
				}
				if ((lvalue instanceof Number)) {
					// return UnaryExpression.access$000((Number)lvalue);
					return (Number) lvalue;
				}
				throw new RuntimeException("Cannot call negate operation on: " + lvalue);
			}

			public String getExpressionSymbol() {
				return "-";
			}
		};
	}

	public static BooleanExpression createNOT(BooleanExpression left) {
		return new BooleanUnaryExpression(left) {
			public Object evaluate(Message message) throws JMSException {
				Boolean lvalue = (Boolean) this.right.evaluate(message);
				if (lvalue == null) {
					return null;
				}
				return lvalue.booleanValue() ? Boolean.FALSE : Boolean.TRUE;
			}

			public String getExpressionSymbol() {
				return "NOT";
			}
		};
	}

	private static Number negate(Number left) {
		if ((left instanceof Integer)) {
			return new Integer(-left.intValue());
		}
		if ((left instanceof Long)) {
			return new Long(-left.longValue());
		}

		return new Double(-left.doubleValue());
	}

	public UnaryExpression(Expression left) {
		this.right = left;
	}

	public Expression getRight() {
		return this.right;
	}

	public void setRight(Expression expression) {
		this.right = expression;
	}

	public String toString() {
		return "(" + getExpressionSymbol() + " " + this.right.toString() + ")";
	}

	public int hashCode() {
		return toString().hashCode();
	}

	public boolean equals(Object o) {
		if ((o == null) || (!getClass().equals(o.getClass()))) {
			return false;
		}
		return toString().equals(o.toString());
	}

	public abstract String getExpressionSymbol();

	static abstract class BooleanUnaryExpression extends UnaryExpression implements BooleanExpression {
		public BooleanUnaryExpression(Expression left) {
			super(left);
		}
	}
}